﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using System.Web.Routing;
using System.ServiceModel.Channels;
namespace Presentation.Web.Core.AjaxRedirect
{
    public class AjaxRedirectAttribute : ActionFilterAttribute
    {
        // private const string RedirectScript = "window.location.href=\"{0}\";";

        // replace() does not put the originating page in the session history,
        // meaning the user will be able to go back to previous page with one back button click.
        private const string RedirectScript = "window.location.replace(\"{0}\");";

        public override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            // only handle Ajax requests
            if (!filterContext.HttpContext.Request.IsAjaxRequest())
                return;

            var result = filterContext.Result;
            // only handle redirect
            if (!(result is RedirectResult) && !(result is RedirectToRouteResult))
                return;

            string destinationUrl = GenerateUrl(result, filterContext.RequestContext);

            if (string.IsNullOrEmpty(destinationUrl))
            {
                throw new InvalidOperationException("No route in the route table matches the supplied values.");
            }

            filterContext.Controller.TempData.Keep();

            filterContext.Result = new JavaScriptResult { Script = GenerateRedirectScript(destinationUrl) };
        }

        private static string GenerateUrl(ActionResult result, System.Web.Routing.RequestContext requestContext)
        {
            RedirectToRouteResult redirectToRouteResult = result as RedirectToRouteResult;
            if (redirectToRouteResult != null)
            {
                return UrlHelper.GenerateUrl(
                    redirectToRouteResult.RouteName,
                    null /* actionName */,
                    null /* controllerName */,
                    redirectToRouteResult.RouteValues,
                    RouteTable.Routes,
                    requestContext,
                    false /* includeImplicitMvcValues */);
            }

            RedirectResult redirectResult = result as RedirectResult;
            if (redirectResult != null)
            {
                return UrlHelper.GenerateContentUrl(redirectResult.Url, requestContext.HttpContext);
            }

            // it will never reach here.
            throw new ArgumentException(null, "result");
        }

        private static string GenerateRedirectScript(string destinationUrl)
        {
            return String.Format(RedirectScript, destinationUrl);
        }
    }
}
